package com.zmc.lostfound.auth.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zmc.lostfound.auth.dao.UserRoleDao;
import com.zmc.lostfound.auth.entity.UserRoleEntity;
import com.zmc.lostfound.auth.service.UserRoleService;
import com.zmc.lostfound.auth.vo.UserRoleSaveVO;
import com.zmc.lostfound.common.exception.MyException;
import com.zmc.lostfound.common.utils.Result;
import com.zmc.lostfound.common.utils.redis.RedisCacheUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.zmc.lostfound.common.constant.RedisConstant.CACHE_ROLE_PERMISSION_KEY_PREFIX;

/**
 * @author ZMC
 * @email 2869581855@qq.com
 * @description 用户信息管理业务实现类
 * @date 2023-07-05 15:17:37
 */
@Service
public class UserRoleServiceImpl extends ServiceImpl<UserRoleDao, UserRoleEntity> implements UserRoleService {

    private final RedisCacheUtil redisCacheUtil;

    public UserRoleServiceImpl(RedisCacheUtil redisCacheUtil) {
        this.redisCacheUtil = redisCacheUtil;
    }

    /**
     * 新增用户&角色关联信息
     *
     * @param userRoleSaveVO 用户&角色关联信息新增/修改请求体
     * @return Result
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result insertUserRole(UserRoleSaveVO userRoleSaveVO) {
        Long userId = userRoleSaveVO.getUserId();
        UserRoleEntity userRoleEntity = this.query()
                .eq("user_id", userId)
                .eq("role_id", userRoleSaveVO.getRoleId()).one();
        if (userRoleEntity != null) {
            MyException.throwException("新增失败: 该用户&角色关联信息已存在，请勿重复添加");
        }
        userRoleEntity = BeanUtil.copyProperties(userRoleSaveVO, UserRoleEntity.class);
        if (!this.save(userRoleEntity)) {
            MyException.throwException("新增用户&角色关联信息失败");
        }
        redisCacheUtil.deleteByKey(CACHE_ROLE_PERMISSION_KEY_PREFIX + userId);
        return Result.ok("新增成功");
    }

    /**
     * 修改用户&角色关联信息
     *
     * @param userRoleSaveVO 用户&角色关联信息新增/修改请求体
     * @return Result
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result updateUserRole(UserRoleSaveVO userRoleSaveVO) {
        Long userId = userRoleSaveVO.getUserId();
        UserRoleEntity userRoleEntity = this.query()
                .eq("user_id", userId)
                .eq("role_id", userRoleSaveVO.getRoleId()).one();
        if (userRoleEntity != null) {
            MyException.throwException("修改失败: 该用户&角色关联信息已存在");
        }
        userRoleEntity = BeanUtil.copyProperties(userRoleSaveVO, UserRoleEntity.class);
        if (!this.updateById(userRoleEntity)) {
            MyException.throwException("修改用户&角色关联信息失败");
        }
        redisCacheUtil.deleteByKey(CACHE_ROLE_PERMISSION_KEY_PREFIX + userId);
        return Result.ok("修改成功");
    }

    /**
     * 按主键ids批量删除用户&角色关联信息
     *
     * @param ids 主键ids
     * @return Result
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result deleteBatchByIds(List<Long> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            MyException.throwException("删除失败: 主键ids为空");
        }
        this.removeByIds(ids);
        return Result.ok("删除成功");
    }

    /**
     * 按用户id和角色id删除用户&角色关联信息
     *
     * @param userId 用户id
     * @param roleId 角色id
     * @return Result
     */
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public Result deleteByUserIdAndRoleId(Long userId, Long roleId) {
        if (userId == null && roleId == null) {
            MyException.throwException("用户id与角色id不能同时为null");
        }
        this.remove(new QueryWrapper<UserRoleEntity>()
                .eq(userId != null, "user_id", userId)
                .eq(roleId != null, "role_id", roleId));
        if (userId != null) {
            redisCacheUtil.deleteByKey(CACHE_ROLE_PERMISSION_KEY_PREFIX + userId);
        }
        return Result.ok("删除成功");
    }

}